/*
 * @Author: lzg2021 854378082@qq.com
 * @Date: 2022-06-15 08:59:50
 * @LastEditors: 李志刚
 * @LastEditTime: 2023-01-17 11:38:53
 * @FilePath: \www.gamemc.com\resources\js\home\api\http.js
 * @Description: axios封装,请求拦截、响应拦截、错误统一处理，AES/RSA加密解密，base64在url里转义是个坑，需要转成16位
 */
import axios from 'axios';
import func from '../utils/func';
import router from '.././router/router';
import store from '.././store/store'
import { LOGIN } from '.././store/mutation_types'
import { showLoadingToast,closeToast,showToast,showFailToast,allowMultipleToast } from 'vant';
// 不允许多个弹出框
allowMultipleToast(false);
/**
  * 跳转登录页
  * 携带当前页面路由，以期在登录页面完成登录后返回当前页面
  */
const toLogin = () => {
    router.replace({
        path: '/login',
        query: {
            redirect: router.currentRoute.fullPath
        }
    });
}

/**
  * 请求失败后的错误统一处理
  * @param {Number} status 请求失败的状态码
  */
const errorHandle = (status, other) => {
    // 状态码判断
    switch (status) {
        // 401: 未登录状态，跳转登录页
        case 401:
            showToast({
                message:other
            });
            store.commit('LOGOUT');
            toLogin();
            break;
        // 验证没通过
        case 422:
            showToast({
                message:other
            });
            break;
        // 404请求不存在
        case 404:
            showToast({
                message:'请求的资源不存在...'
            });
            break;

        default:
            showToast({
                message:'服务器有点忙...'
            });
            console.log(other);
            break;
    }
}

// 创建axios实例
const instance = axios.create({ timeout: 1000 * 15 });
// 设置post请求头
instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
/**
  * 请求拦截器
  * 每次请求前，如果存在token则在请求头中携带token
  */
instance.interceptors.request.use(
    config => {
        // 登录流程控制中，根据本地是否存在token判断用户的登录情况
        // 但是即使token存在，也有可能token是过期的，所以在每次的请求头中携带token
        // 后台根据携带的token判断用户的登录情况，并返回给我们对应的状态码
        // 而后我们可以在响应拦截器中，根据状态码进行一些统一的操作。
        // store.getters.token 这里给存成了变量，不会更新，有点问题
        let token = store.getters.token;
        // console.log('request token',token)
        token && (config.headers.Authorization = token);
        if (!token) {
            token = 'fireflycoltd.com'
        }
        // GET、POST 的取参数方式不同，坑死，对应的富文本内容也会被过滤，所以只签名了token+time两个字段
        let sign_str = {
            token: token,
            timestamp: (new Date()).getTime()
        }
        const sign = func.getSign(sign_str);
        // const rsa = func.RSAencrypted(token);
        // 文件上传需要特殊处理
        const patt = new RegExp("/api/upload/");
        if(patt.test(config.url)){
            config.headers['content-type'] = "multipart/form-data";
        }
        if (config.method == 'get' || patt.test(config.url)) {
            config.params = {
                ...config.params,
                sign: sign,
                // rsa:rsa,
            }
        } else {
            //  + "&rsa=" + rsa
            config.data = config.data + '&sign=' + sign;
        }
        // console.log('请求数据',config)
        showLoadingToast({
            forbidClick:true,
            overlay:true,
            message:'数据加载中...',
        });
        return config;
    },
    error => {
        console.log('请求报错',error);
        return Promise.error(error);
    }
);

// 响应拦截器
instance.interceptors.response.use(
    // 请求成功
    res => {
        closeToast();
        if (res.status === 200) {
            // 状态码判断
            let returnCode = false;
            switch (res.data.code) {
                // 400参数的错误
                case 400:
                    showToast({
                        message:res.data.message
                    });
                    break;

                case 422:
                    showToast({
                        message:res.data.message
                    });
                    break;

                // 401: 未登录状态，跳转登录页
                case 401:
                    showToast({
                        message:res.data.message
                    });
                    store.commit('LOGOUT');
                    toLogin();
                    break;
                // 402没有接口权限
                case 402:
                    showToast({
                        message:res.data.message
                    });
                    break;

                // 403 输入正确，但其它相关数据有问题，拒绝继续执行
                case 403:
                    showToast({
                        message:res.data.message
                    });
                    break;

                // 404请求不存在
                case 404:
                    showToast({
                        message:'请求的资源不存在'
                    });
                    break;

                // 200 正确返回
                case 200:
                    // 把返回的 authorization 放到token里边，刷新token，不刷新只是不能保证一直有效并不是会立即失败，获取验证码等有些不需要更新
                    if(undefined != res.headers.authorization){
                        let tokenData = {
                            id: store.getters.user_id,
                            name: store.getters.user_name,
                            token: res.headers.authorization,
                        };
                        store.commit(LOGIN, tokenData)
                    }
                    // console.log('reponse token: ',localStorage.getItem("token"))
                    Promise.resolve(res)
                    returnCode = true;
                    break;

                default:
                    showToast({
                        message:'服务器有点忙...'
                    });
                    break;
            }
            if(returnCode){
                return res.data;
            }else{
                return Promise.reject(res);
            }
        } else {
            // console.log(res)
            return Promise.reject(res);
        }
    },
    // 请求失败
    error => {
        closeToast();
        const { response } = error;
        if (response) {
            // 请求已发出，但是不在2xx的范围
            errorHandle(response.status, response.data.message);
            return Promise.reject(response);
        } else {
            // 处理断网的情况
            // eg:请求超时或断网时，更新state的network状态
            // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
            // 关于断网组件中的刷新重新获取数据，会在断网组件中说明
            showFailToast({
                message:'请检查您的网络情况...'
            });
        }
    });

export default instance;
